﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using TCCCompiler;
using TCCHWLib;
using UrielGuy.SyntaxHighlightingTextBox;
using TCCHWLib.Commands;
using System.IO;
using TCCUIControls;

namespace TCCEmulator
{
    public partial class IDE : Form
    {
        private Compiler m_Compiler;
        private EmulatorForm m_EmulatorForm;
        private bool m_IsEmulatorAttached = false;
        private bool m_IsCodeBuilt = false;

        public IDE()
        {
            InitializeComponent();
            InitializeForm();
        }

        private void InitializeForm()
        {
            m_Compiler = new Compiler();
            Configuration.LoadConfiguration();

            rtbCode.WordWrap = false;
            rtbCode.Seperators.AddRange(new char[] { ' ', ';', '\t', '\r', '\n', '{', '}', '[', ']', '(', ')' });

            customizeToolStripMenuItem.Checked = m_IsEmulatorAttached;

            InitializeSourceCodeEditor(rtbCode);
            //Configuration.SaveConfiguration();
            //Configuration.LoadConfiguration();
        }
        private void InitializeSourceCodeEditor(SyntaxHighlightingTextBox rtb)
        {
            // Blocks
            rtb.HighlightDescriptors.Add(new HighlightDescriptor("<code>", Color.DarkOrchid, null, DescriptorType.Word, DescriptorRecognition.WholeWord, true));
            rtb.HighlightDescriptors.Add(new HighlightDescriptor("</code>", Color.DarkOrchid, null, DescriptorType.Word, DescriptorRecognition.WholeWord, true));
            rtb.HighlightDescriptors.Add(new HighlightDescriptor("<data>", Color.DarkOrchid, null, DescriptorType.Word, DescriptorRecognition.WholeWord, true));
            rtb.HighlightDescriptors.Add(new HighlightDescriptor("</data>", Color.DarkOrchid, null, DescriptorType.Word, DescriptorRecognition.WholeWord, true));

            // Datatypes
            rtb.HighlightDescriptors.Add(new HighlightDescriptor("int", Color.Blue, null, DescriptorType.Word, DescriptorRecognition.WholeWord, true));
            rtb.HighlightDescriptors.Add(new HighlightDescriptor("char", Color.Blue, null, DescriptorType.Word, DescriptorRecognition.WholeWord, true));

            // Reserved Words
            rtb.HighlightDescriptors.Add(new HighlightDescriptor("main", Color.Blue, null, DescriptorType.Word, DescriptorRecognition.WholeWord, true));
            rtb.HighlightDescriptors.Add(new HighlightDescriptor("if", Color.Blue, null, DescriptorType.Word, DescriptorRecognition.WholeWord, true));
            rtb.HighlightDescriptors.Add(new HighlightDescriptor("else", Color.Blue, null, DescriptorType.Word, DescriptorRecognition.WholeWord, true));
            rtb.HighlightDescriptors.Add(new HighlightDescriptor("while", Color.Blue, null, DescriptorType.Word, DescriptorRecognition.WholeWord, true));
            rtb.HighlightDescriptors.Add(new HighlightDescriptor("for", Color.Blue, null, DescriptorType.Word, DescriptorRecognition.WholeWord, true));
            rtb.HighlightDescriptors.Add(new HighlightDescriptor("lock", Color.Blue, null, DescriptorType.Word, DescriptorRecognition.WholeWord, true));

            // TCC Keywords
            rtb.HighlightDescriptors.Add(new HighlightDescriptor("atomic", Color.DarkGoldenrod, null, DescriptorType.Word, DescriptorRecognition.WholeWord, true));
            rtb.HighlightDescriptors.Add(new HighlightDescriptor("retry", Color.DarkGoldenrod, null, DescriptorType.Word, DescriptorRecognition.WholeWord, true));
            rtb.HighlightDescriptors.Add(new HighlightDescriptor("wait", Color.DarkGoldenrod, null, DescriptorType.Word, DescriptorRecognition.WholeWord, true));

            // Comments
            rtb.HighlightDescriptors.Add(new HighlightDescriptor("/*", "*/", Color.Green, null, DescriptorType.ToCloseToken, DescriptorRecognition.StartsWith, false));
            rtb.HighlightDescriptors.Add(new HighlightDescriptor("//", Color.Green, null, DescriptorType.ToEOL, DescriptorRecognition.StartsWith, false));
        }

        private void LoadSourceCode(string filename)
        {
            StreamReader sr = new StreamReader(filename);
            rtbCode.Text = sr.ReadToEnd();
            sr.Close();
        }

        private void compileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Compile();
        }

        private void PrototypeCompilerForm_Shown(object sender, EventArgs e)
        {
            LoadSourceCode("SampleCode_1.txt");
        }
        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                LoadSourceCode(openFileDialog1.FileName);
            }
        }

        private void IDE_Move(object sender, EventArgs e)
        {
            if (m_IsEmulatorAttached)
                if (m_EmulatorForm != null)
                    m_EmulatorForm.SetDesktopLocation(this.DesktopLocation.X + this.Width, this.DesktopLocation.Y);
        }

        private void IDE_Resize(object sender, EventArgs e)
        {
            if (m_IsEmulatorAttached)
                if (m_EmulatorForm != null)
                    m_EmulatorForm.SetDesktopLocation(this.DesktopLocation.X + this.Width, this.DesktopLocation.Y);
        }
        private void Compile()
        {
            List<string> listData = new List<string>();
            List<string> listCode = new List<string>();

            GetDataAndCodeSegments(rtbCode, listData, listCode);

            m_Compiler.Compile(listData, listCode, tvData, tvCode, rtbOutput);

            UpdateTreeViewsExpansion(tvData.Nodes[0]);
            UpdateTreeViewsExpansion(tvCode.Nodes[0]);

            m_IsCodeBuilt = true;
        }

        private void UpdateTreeViewsExpansion(TreeNode node)
        {
            if (node.Text == "Data" || node.Text == "Code" ||
                node.Text == "Atomic_Block" || node.Text == "Sequence_Of_Statements")
                node.Expand();

            foreach (TreeNode child in node.Nodes)
                UpdateTreeViewsExpansion(child);
        }

        private void GetDataAndCodeSegments(RichTextBox rtbCode, List<string> listData, List<string> listCode)
        {
            List<string> lines = new List<string>(rtbCode.Lines);
            int i = 0;

            while (lines[i].Trim() == "")
                i++;

            if (lines[i].Trim() == "<data>")
            {
                i++;

                while (lines[i].Trim() != "</data>")
                    listData.Add(lines[i++]);

                i++;
            }

            while (lines[i].Trim() != "<code>")
                i++;

            i++;

            while (lines[i].Trim() != "</code>")
                listCode.Add(lines[i++]);

            i++;
        }

        private void customizeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            m_IsEmulatorAttached = !m_IsEmulatorAttached;
            customizeToolStripMenuItem.Checked = m_IsEmulatorAttached;
        }

        private void runToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!m_IsCodeBuilt)
                compileToolStripMenuItem.PerformClick();

            m_EmulatorForm = EmulatorForm.TheEmulatorForm;
            if (m_IsEmulatorAttached)
            {
                m_EmulatorForm.SetDesktopLocation(this.DesktopLocation.X + this.Width, this.DesktopLocation.Y);
                m_EmulatorForm.StartPosition = FormStartPosition.Manual;
            }
            else
                m_EmulatorForm.StartPosition = FormStartPosition.CenterScreen;

            m_EmulatorForm.Show();
            this.Focus();
        }

        private void rtbCode_TextChanged(object sender, EventArgs e)
        {
            m_IsCodeBuilt = false;
        }
    }
}
